package com.fileshare.web.utils;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.AppendObjectRequest;
import com.aliyun.oss.model.PutObjectRequest;
import com.fileshare.web.dto.UploadItem;
import com.fileshare.web.entity.User;
import com.fileshare.web.exception.FsRuntimeException;
import com.fileshare.web.properties.AliOssProperties;
import org.springframework.util.DigestUtils;

import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Date;

import static com.fileshare.web.constant.CommonConstant.DOT;

public class AliOssUtil {
    private AliOssUtil() {
    }

    public static void uploadFile(AliOssProperties parameter, UploadItem item) {
        OSS ossClient = getOssClient(parameter);
        try {
            PutObjectRequest putObjectRequest = getPutObjectRequest(parameter, item);
            if (item.isFragment()) {
                uploadFragment(parameter, ossClient, item);
            } else {
                ossClient.putObject(putObjectRequest);
            }
        } catch (OSSException | ClientException e) {
            throw new FsRuntimeException(e);
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    public static String uploadSingleFile(AliOssProperties parameter, UploadItem item, User user) {
        OSS ossClient = getOssClient(parameter);
        try {
            PutObjectRequest putObjectRequest = getPutObjectRequest(parameter, item);
            if (item.isFragment()) {
                uploadFragment(parameter, ossClient, item);
            } else {
                ossClient.putObject(putObjectRequest);
            }
            return String.format(
                    "http://%s.oss-cn-beijing.aliyuncs.com/%s", parameter.getBucket(),
                    getCustomFilePath(user, item.getOriginName())
            );
        } catch (OSSException | ClientException e) {
            throw new FsRuntimeException(e);
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    private static void uploadFragment(AliOssProperties parameter, OSS ossClient, UploadItem item) {
        AppendObjectRequest appendObjectRequest = new AppendObjectRequest(
                parameter.getBucket(), item.getUploadName(), item.getFileContent()
        );
        appendObjectRequest.setPosition(item.getOffset());
        ossClient.appendObject(appendObjectRequest);
    }

    public static PutObjectRequest getPutObjectRequest(AliOssProperties parameter, UploadItem item) {
        return new PutObjectRequest(
                parameter.getBucket(), item.getUploadName(), item.getFileContent()
        );
    }

    public static OSS getOssClient(AliOssProperties parameter) {
        if (parameter.getSecurityToken() != null) {
            return new OSSClientBuilder().build(
                    parameter.getEndpoint(), parameter.getAccessKeyId(),
                    parameter.getAccessKeySecret(), parameter.getSecurityToken()
            );
        }
        return new OSSClientBuilder().build(
                parameter.getEndpoint(), parameter.getAccessKeyId(),
                parameter.getAccessKeySecret()
        );
    }

    public static String genTempDownloadUrl(AliOssProperties parameter, String objectName, long expired) {
        OSS ossClient = getOssClient(parameter);
        Date expiration = new Date(new Date().getTime() + expired);
        URL url = ossClient.generatePresignedUrl(parameter.getBucket(), objectName, expiration);
        ossClient.shutdown();
        return url.toString();
    }

    public static String getCustomFilePath(User user, String filename) {
        String hashName = DigestUtils.md5DigestAsHex(filename.getBytes(StandardCharsets.UTF_8));
        String extend = filename.substring(filename.lastIndexOf(DOT));
        return user.getUserSeq() + "/" + hashName + extend;
    }
}
